package me.yan.interceptor;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import me.yan.constant.Types;
import me.yan.constant.WebConst;
import me.yan.pojo.UserDomain;
import me.yan.service.user.UserService;
import me.yan.utils.IPKit;
import me.yan.utils.MapCache;
import me.yan.utils.TaleUtils;
import me.yan.utils.UUID;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.nio.file.Paths;
import java.util.Locale;

@Slf4j
@Component
public class BaseInterceptor implements HandlerInterceptor {

    private static final Logger LOGGER = log;
    private static final String USER_AGENT = "user-agent";
    protected MapCache cache=MapCache.single();
    @Autowired
    private UserService userService;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object o) throws Exception {
        String uri = normalizeRequestUri(request);

        // 规范化路径，防止路径遍历
        uri = uri.replaceAll("/+", "/");
        System.out.println("uri:"+uri);


        LOGGER.info("UserAgent: {}", request.getHeader(USER_AGENT));
        LOGGER.info("用户访问地址: {}, 来路地址: {}", uri, IPKit.getIpAddrByRequest(request));
        // 获取当前登录用户
        UserDomain user = TaleUtils.getLoginUser(request);
        if (user == null) {
            System.out.println("uri======"+uri);
            System.out.println("request======"+ request.getRequestURI());
            Integer uid = TaleUtils.getCookieUid(request);
            if (uid != null) {
                user = userService.getUserInfoById(uid);
                request.getSession().setAttribute(WebConst.LOGIN_SESSION_KEY, user);
            }
        }

        // 权限控制
        if (isAdminPath(uri)
                && !uri.matches("^/admin/login(/.*)?") // 严格匹配/admin/login路径
                && user == null
                && !isStaticResource(uri)) {

            response.sendRedirect(request.getContextPath() + "/admin/login");
            return false;
        }

        // 检查权限：对于敏感操作路径（如删除），确保用户是管理员
        if (isSensitiveOperation(uri) && user == null) {
            response.sendError(HttpServletResponse.SC_FORBIDDEN, "Unauthorized access");
            return false;
        }

        // 设置 CSRF token，仅对敏感操作进行校验
        if ("GET".equalsIgnoreCase(request.getMethod())) {
            String csrfToken = UUID.UU64();
            cache.hset(Types.CSRF_TOKEN.getType(), csrfToken, uri, 30 * 60);
            request.setAttribute("_csrf_token", csrfToken);
        } else if ("POST".equalsIgnoreCase(request.getMethod()) && isSensitiveOperation(uri) && user == null) {
            // 检查 POST 请求的 CSRF token
            String csrfToken = request.getParameter("_csrf_token");
            String expectedUri = cache.hget(Types.CSRF_TOKEN.getType(), csrfToken);
            if (expectedUri == null || !expectedUri.equals(uri)) {
                response.sendError(HttpServletResponse.SC_FORBIDDEN, "CSRF token invalid or expired.");
                return false;
            }
            cache.hdel(Types.CSRF_TOKEN.getType(), csrfToken);
        }

        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
    }



    private String normalizeRequestUri(HttpServletRequest request) throws UnsupportedEncodingException {
        String rawUri = request.getRequestURI();
        String decodedUri = deepDecode(rawUri);

        // 修复：移除分号及后续路径参数
        int semicolonIndex = decodedUri.indexOf(';');
        if (semicolonIndex > -1) {
            decodedUri = decodedUri.substring(0, semicolonIndex);
        }

        // 规范化路径（处理"."和".."）
        String normalized = Paths.get(decodedUri).normalize().toString().replace("\\", "/");
        return normalized.toLowerCase(Locale.ROOT);
    }

    public String deepDecode(String uri) throws UnsupportedEncodingException {
        String prev;
        String decoded = uri;
        do {
            prev = decoded;
            decoded = URLDecoder.decode(prev, "UTF-8");
        } while (!prev.equals(decoded));
        return decoded;
    }
    private boolean isAdminPath(String uri) {
        return uri.matches("^/admin(/.*)?$");
    }
    /**
     * 检查是否为静态资源文件
     */
    private boolean isStaticResource(String uri) {
        return uri.startsWith("/admin/css") || uri.startsWith("/admin/images")
                || uri.startsWith("/admin/js") || uri.startsWith("/admin/plugins")
                || uri.startsWith("/admin/editormd");
    }
    /**
     * 检查是否为敏感操作路径（例如：删除、更新等操作）
     */
    private boolean isSensitiveOperation(String uri) {
        return uri.contains("/delete") || uri.contains("/update") || uri.contains("/create");
    }
}
